package com.xl.service.impl;

import com.alibaba.excel.EasyExcel;
import com.xl.annotation.Excel;
import com.xl.domain.pojo.Device;
import com.xl.domain.pojo.DeviceTo;
import com.xl.enums.DeviceTypeEnum;
import com.xl.service.StudyExcelService;
import com.xl.utils.excel.handler.MySheetWriteHandler;
import com.xl.utils.excel.util.EasyExcelUtils;
import com.xl.utils.excel.util.MyExcelUtil;
import com.xl.utils.excel.util.PriExcelUtil;
import com.xl.utils.str.StringUtils;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class StudyExcelServiceImpl implements StudyExcelService {

    @Override
    public void downloadTemplate(HttpServletResponse response) throws IOException {
        //文件名
        String fileName = URLEncoder.encode("数据模板", "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        MySheetWriteHandler mySheetWriteHandler = sheetCustomConfig();
        //设置指定列输入的数据类型为字符
        EasyExcel.write(response.getOutputStream(), Device.class)
                .registerWriteHandler(mySheetWriteHandler)//指定某几列输入类型为字符
                //.registerWriteHandler(new MyCellWriteHander()) 设置单元格的格式
                .sheet("设备列表")
                .doWrite(null);

    }

    @Override
    public void export(HttpServletResponse response, String deviceName) {
        List<Device> deviceList = Device.getDeviceList();
        //根据设备名字，进行模糊查询
        List<Device> exportData = new ArrayList<>();
        if (StringUtils.isNotBlank(deviceName)) {
            exportData = deviceList.stream().filter(item -> item.getDeviceName().contains(deviceName)).collect(Collectors.toList());
        } else {
            exportData = deviceList;
        }
        //如果不显示查询条件直接下面这两句就可以实现数据导出了
        //MyExcelUtil<Device> util = new MyExcelUtil<>(Device.class);
        //util.exportExcel(response,exportData,"设备列表",null);

        PriExcelUtil<Device> priExcelUtil = new PriExcelUtil<>(Device.class);
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        priExcelUtil.init(exportData, "设备列表", null, Excel.Type.EXPORT);
        priExcelUtil.writeSheet();
        //表格追加查询信息
        Sheet sheet = priExcelUtil.getSheet();
        //从表里面的第一个行到最后一行（应该是有数据的第一行-最后一样），向下平移2行  -> 这样表格上面就有两个空行了，就可添加数据了 。
        sheet.shiftRows(sheet.getFirstRowNum(), sheet.getLastRowNum(), 2);
        Row row = sheet.createRow(0);  //在首行创建一行 用于显示搜索条件
        row.createCell(0).setCellValue("设备名称：" + (StringUtils.isNotBlank(deviceName) ? deviceName : ""));

        //导出
        try {
            priExcelUtil.getWb().write(response.getOutputStream());
        } catch (Exception e) {
            System.err.println("导出Excel异常---" + e.getMessage());
        } finally {
            IOUtils.closeQuietly(priExcelUtil.getWb());
        }
    }

    @Override
    public void exportDirect(HttpServletResponse response) {
        List<Device> deviceList = Device.getDeviceList();
        MyExcelUtil<Device> util = new MyExcelUtil<>(Device.class);
        util.exportExcel(response, deviceList, "设备列表");
    }

    @Override
    public void importAndParseExcel(MultipartFile file, Boolean checkExcelHead) {
        List<DeviceTo> devicesTos = EasyExcelUtils.readExcel(file, DeviceTo.class, checkExcelHead);
        devicesTos.forEach(System.out::println);
        //这个时候得到的是原始数据，里面大多数的数据都是字符串类型，但是有些枚举类数据库中存储的是int类型，因此需要类型转换
        List<Device> devices = convertToDeviceEntity(devicesTos);
        devices.forEach(System.out::println);
    }

    /**
     * DeviceTo转为Device对象，主要是有些属性的数据类型不同
     * 1 检查除id外所有字段不能为null
     * 2 将 设备类型转为对应的type（int）  将主备转为对应的type（int）
     *
     * @param devicesTos
     * @return
     */
    private List<Device> convertToDeviceEntity(List<DeviceTo> devicesTos) {
        List<Device> devices = new ArrayList<>();
        for (int i = 0; i < devicesTos.size(); i++) {
            DeviceTo deviceTo = devicesTos.get(i);
            Device device = new Device();
            String prefix = "第" + (i + 1) + "行";

            device.setId(deviceTo.getId());
            if (StringUtils.isBlank(deviceTo.getDeviceCode())) {
                throw new RuntimeException(prefix + "设备编码不能为空");
            }
            device.setDeviceCode(deviceTo.getDeviceCode());
            if (StringUtils.isBlank(deviceTo.getDeviceName())) {
                throw new RuntimeException(prefix + "设备名称不能为空");
            }
            device.setDeviceName(deviceTo.getDeviceName());
            if (StringUtils.isBlank(deviceTo.getDomainName())) {
                throw new RuntimeException(prefix + "设备域名不能为空");
            }
            device.setDomainName(deviceTo.getDomainName());
            if (StringUtils.isNull(deviceTo.getDeviceType())) {
                throw new RuntimeException(prefix + "设备类型不能为空");
            }
            device.setDeviceType(DeviceTypeEnum.getTypeByInfo(deviceTo.getDeviceType()));
            if (StringUtils.isBlank(deviceTo.getMasterAndSlave())) {
                throw new RuntimeException(prefix + "主备类型不能为空");
            }
            String masterSlaveString = deviceTo.getMasterAndSlave();
            if (masterSlaveString.equals("主")) {
                device.setMasterAndSlave(1);
            } else if (masterSlaveString.equals("备")) {
                device.setMasterAndSlave(0);
            } else {
                throw new RuntimeException("系统中不存在该设备类型！");
            }
            if (StringUtils.isBlank(deviceTo.getIpAddress())) {
                throw new RuntimeException(prefix + "设备ip不能为空");
            }
            device.setIpAddress(deviceTo.getIpAddress());

            devices.add(device);
        }
        return devices;
    }

    /**
     * 为sheet中的某几列设置下拉数据
     * 为sheet中的某几列设置输入格式为字符
     *
     * @return
     */
    private MySheetWriteHandler sheetCustomConfig() {
        //设置某几列的输入为字符
        MySheetWriteHandler mySheetWriteHandler = new MySheetWriteHandler();
        mySheetWriteHandler.setUseStringColunms(new Integer[]{2, 3}); //设置第三第四列的输入为字符
        //某几列需要设置下拉数据
        Map<Integer, String[]> dropDownData = new HashMap();
        dropDownData.put(1, DeviceTypeEnum.getAllInfo());//为第二列设置下拉数据
        dropDownData.put(4, new String[]{"主", "备"});//为第五列设置下拉数据
        mySheetWriteHandler.setDropDownData(dropDownData);
        return mySheetWriteHandler;
    }

}
